#include "CLevel.h"
#include <Windows.h>
#include <fstream>
#include <iostream>
#include "CTileManager.h"
#include "SGD Wrappers/CSGD_TextureManager.h"
#include <vector>
#include "CLayer.h"
#include "CTile.h"
#include <stdlib.h>
#include "CProfileManager.h"
#include "CSpawnpoint.h"
#include "Mail System.h"
#include "CObjectManager.h"

CLevel::CLevel()
{

}

CLevel::~CLevel()
{
	for(unsigned int i = 0; i < m_vecSpawnpoints.size(); i++)
		delete m_vecSpawnpoints[i];
	m_vecSpawnpoints.clear();
}

void CLevel::Enter(char* szFileName)
{
	///////////////////////////////////////////////////////
	//	Start Code Profiler
	//CProfileManager::GetInstance()->StartProfile("Level_Load");
	//
	///////////////////////////////////////////////////////

	fstream fin(szFileName, ios::in | ios::binary);
	fin.exceptions(~std::ios_base::goodbit);
	try
	{
		///////////////////////////////////////////////////////////
		//	Temp Variables O.o
		char szFile[256];
		int nTemp;
		unsigned int byteStrLen = 0;
		unsigned int byteStrLenCon = 0;
		//
		///////////////////////////////////////////////////////////

		///////////////////////////////////////////////////////////
		//	TileSet
		//		Filename of TileSet Image
		fin.read((char*)&byteStrLen, sizeof(char));
		fin.clear();
		if(byteStrLen >=127)
		{
			fin.read((char*)&byteStrLenCon, sizeof(char));
			fin.clear();
		}
		memset(szFile,0,byteStrLen+byteStrLenCon);
		fin.read(szFile, byteStrLen+byteStrLenCon);
		fin.clear();
		szFile[byteStrLen+byteStrLenCon] = 0;
		char buffer[256];
		sprintf_s(buffer, _countof(buffer), "Resource/Tilesets/%s", szFile);
		CTileManager::GetInstance()->TileSetImage(CSGD_TextureManager::GetInstance()->LoadTexture(buffer));
		//		Width of Tiles
		fin.read((char*)&nTemp, sizeof(int));
		fin.clear();
		CTileManager::GetInstance()->TileWidth(nTemp);
		//		Height of Tiles
		fin.read((char*)&nTemp, sizeof(int));
		fin.clear();
		CTileManager::GetInstance()->TileHeight(nTemp);
		//
		///////////////////////////////////////////////////////////

		///////////////////////////////////////////////////////////
		//	WorldMap
		//		Width of Map
		fin.read((char*)&nTemp, sizeof(int));
		fin.clear();
		CTileManager::GetInstance()->MapWidth(nTemp);
		//		Height of Map
		fin.read((char*)&nTemp, sizeof(int));
		fin.clear();
		CTileManager::GetInstance()->MapHeight(nTemp);
		//		Number of Layers
		int nTempCount;
		fin.read((char*)&nTempCount, sizeof(int));
		fin.clear();
		//		Clear Layer Vector
		CTileManager::GetInstance()->Clear();
		//		Loop Thru the Amount of Layers
		for(int i = 0; i < nTempCount; i++)
		{
		//		Create Temporary Layer and Tile Variables
			CLayer* tempLayer = new CLayer();
			CTileManager::GetInstance()->AddLayer(tempLayer);
			int nTempX;
			int nTempY;
			for(int x = 0; x < CTileManager::GetInstance()->MapWidth(); x++)
			{
				for(int y = 0; y <  CTileManager::GetInstance()->MapHeight(); y++)
				{
		//		Read in Tile Pos
				fin.read((char*)&nTempX, sizeof(int));
				fin.clear();
				fin.read((char*)&nTempY, sizeof(int));
				fin.clear();
		//		Add Tile to temp Layer
				CTile* pTempTile = new CTile(nTempX, nTempY);
				//MailSystem::GetInstance()->SendMail(new CreateTileMessage(&pTempTile, nTempX, nTempY));
				CTileManager::GetInstance()->AddTile(i, pTempTile);
				}
			}
		}
		//
		///////////////////////////////////////////////////////////

		///////////////////////////////////////////////////////////
		//	Collision Rects
		fin.read((char*)&nTempCount, sizeof(int));
		fin.clear();
		//	Clear List
		m_vecLevelCollision.clear();
		//	Loop Thru Rects
		for(int i = 0; i < nTempCount; i++)
		{
			int nTempX;
			int nTempY;
			int nTempW;
			int nTempH;
			fin.read((char*)&nTemp, sizeof(int));
			fin.read((char*)&nTempX, sizeof(int));
			fin.read((char*)&nTempY, sizeof(int));
			fin.read((char*)&nTempW, sizeof(int));
			fin.read((char*)&nTempH, sizeof(int));
			MailSystem::GetInstance()->SendMail(new AddLevelCollisionMessage(
				nTemp, nTempX, nTempY, nTempW, nTempH));
		}
		//
		///////////////////////////////////////////////////////////

		///////////////////////////////////////////////////////////
		//	SpawnPoints
		//		Number of SpawnPoints
		fin.read((char*)&nTempCount, sizeof(int));
		m_vecSpawnpoints.clear();
		for(int i = 0; i < nTempCount; i++)
		{
			int nTempX;
			int nTempY;
			fin.read((char*)&nTemp, sizeof(int));
			fin.read((char*)&nTempX, sizeof(int));
			fin.read((char*)&nTempY, sizeof(int));
			AddSpawnPoint(new CSpawnPoint(
				nTemp, (float)nTempX, (float)nTempY));
		}
		//
		///////////////////////////////////////////////////////////

		///////////////////////////////////////////////////////////
		//	Close FileStream
		fin.close();
		//
		///////////////////////////////////////////////////////////
	}
	catch(std::ios_base::failure)
	{
		fin.close();
		MessageBox(NULL,
			"File Read Error","Error",MB_OK);
	}

	///////////////////////////////////////////////////////
	//	End Code Profiler
	//CProfileManager::GetInstance()->StopProfile("Level_Load");
	//
	///////////////////////////////////////////////////////
}

void CLevel::Render()
{
	///////////////////////////////////////////////////////
	//	Start Code Profiler
	//CProfileManager::GetInstance()->StartProfile("Level_Render");
	//
	///////////////////////////////////////////////////////

	CTileManager::GetInstance()->Render();

	///////////////////////////////////////////////////////
	//	End Code Profiler
	//CProfileManager::GetInstance()->StopProfile("Level_Render");
	//
	///////////////////////////////////////////////////////
}

void CLevel::Exit()
{
	for(unsigned int i = 0; i < m_vecSpawnpoints.size(); i++)
		delete m_vecSpawnpoints[i];
	m_vecSpawnpoints.clear();

	CTileManager::GetInstance()->Clear();
}